package com.itrui.commodity.web;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itrui.commodity.common.Code;
import com.itrui.commodity.common.CustomException;
import com.itrui.commodity.common.R;
import com.itrui.commodity.common.Result;
import com.itrui.commodity.dto.ProductDto;
import com.itrui.commodity.pojo.Category;
import com.itrui.commodity.pojo.Product;
import com.itrui.commodity.pojo.ProductLabel;
import com.itrui.commodity.service.CategoryService;
import com.itrui.commodity.service.ProductLabelService;
import com.itrui.commodity.service.ProductService;
import com.itrui.feign.client.PictureClient;
import com.itrui.feign.client.common.Picture;
import io.lettuce.core.dynamic.annotation.Param;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/product")
public class ProductController {

    @Autowired
    private ProductService productService;

    @Autowired
    private ProductLabelService productLabelService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PictureClient pictureClient;

    RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.92.201:9200")));

    /**
     * 商家端新增商品
     *
     * @param productDto
     * @return
     */
    @PostMapping
    public R<String> save(@RequestBody ProductDto productDto) {
        log.info(productDto.toString());

        productService.saveWithLabel(productDto);

        //清理某个分类下面的菜品缓存数据
        String key = "product_" + productDto.getCategoryId() + "_1";
        redisTemplate.delete(key);

        return R.success("新增商品成功");
    }

    /**
     * 商家端商品信息分页查询
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize, String name) {

        //构造分页构造器对象
        Page<Product> pageInfo = new Page<>(page, pageSize);
        Page<ProductDto> ProductDtoPage = new Page<>();

        //条件构造器
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
        //添加过滤条件
        queryWrapper.like(name != null, Product::getName, name);
        //添加排序条件
        queryWrapper.orderByDesc(Product::getUpdateTime);

        //执行分页查询
        productService.page(pageInfo, queryWrapper);


        //对象拷贝
        BeanUtils.copyProperties(pageInfo, ProductDtoPage, "records");

        List<Product> records = pageInfo.getRecords();

        List<ProductDto> list = records.stream().map((item) -> {
            ProductDto ProductDto = new ProductDto();

            BeanUtils.copyProperties(item, ProductDto);

            Long categoryId = item.getCategoryId();//分类id
            //根据id查询分类对象
            Category category = categoryService.getById(categoryId);

            if (category != null) {
                String categoryName = category.getName();
                ProductDto.setCategoryName(categoryName);
            }
            return ProductDto;
        }).collect(Collectors.toList());

        ProductDtoPage.setRecords(list);

        return R.success(ProductDtoPage);
    }

    /**
     * 商家端根据id查询商品信息和对应的标签信息
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<ProductDto> get(@PathVariable Long id) {

        ProductDto productDto = productService.getByIdWithLabel(id);

        return R.success(productDto);
    }

    /**
     * 商家端修改商品
     *
     * @param ProductDto
     * @return
     */
    @PutMapping
    public R<String> update(@RequestBody ProductDto ProductDto) {
        log.info(ProductDto.toString());

        productService.updateWithLabel(ProductDto);

        //清理某个分类下面的菜品缓存数据
        String key = "product_" + ProductDto.getCategoryId() + "_1";
        redisTemplate.delete(key);

        return R.success("修改商品成功");
    }


    /**
     * 用户小程序端获取全部商品
     *
     * @param product
     * @return
     */
    @GetMapping("/list")
    public R<List<ProductDto>> list(Product product) {

        List<ProductDto> ProductDtoList = null;
        //构造key
        String key = "product_" + product.getCategoryId() + product.getStatus();

        //先从redis中获取缓存数据
        ProductDtoList = (List<ProductDto>) redisTemplate.opsForValue().get(key);

        //如果存在直接返回不查数据库
        if (ProductDtoList != null) {
            return R.success(ProductDtoList);
        }


        //构造查询条件
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(product.getCategoryId() != null, Product::getCategoryId, product.getCategoryId());
        //添加条件，查询状态为1（起售状态）的商品
        queryWrapper.eq(Product::getStatus, 1);

        //添加排序条件
        queryWrapper.orderByAsc(Product::getSort).orderByDesc(Product::getUpdateTime);

        List<Product> list = productService.list(queryWrapper);

        ProductDtoList = list.stream().map((item) -> {
            ProductDto ProductDto = new ProductDto();

            BeanUtils.copyProperties(item, ProductDto);

            Long categoryId = item.getCategoryId();//分类id
            //根据id查询分类对象
            Category category = categoryService.getById(categoryId);

            if (category != null) {
                String categoryName = category.getName();
                ProductDto.setCategoryName(categoryName);
            }

            //当前商品的id
            Long ProductId = item.getId();
            LambdaQueryWrapper<ProductLabel> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(ProductLabel::getProductId, ProductId);
            //SQL:select * from Product_Label where Product_id = ?
            List<ProductLabel> ProductLabelList = productLabelService.list(lambdaQueryWrapper);
            ProductDto.setLabels(ProductLabelList);
            return ProductDto;
        }).collect(Collectors.toList());

        //如果不存在需要查询数据库将数据缓存到redis中
        redisTemplate.opsForValue().set(key, ProductDtoList, 60, TimeUnit.SECONDS);


        return R.success(ProductDtoList);
    }

    /***
     * 商家端根据id删除分类
     * @param ids
     * @return
     */
    @DeleteMapping
    public R<String> delete(@RequestParam List<Long> ids) {
        log.info("删除商品，id为：{}", ids);

        //categoryService.removeById(id);
        productService.removeWithLabels(ids);

        return R.success("商品信息删除成功");
    }

    ;

    /**
     * 商家端修改商品状态
     *
     * @param ids
     * @param status
     * @return
     */
    @PutMapping("/status/{status}")
    public R<String> updateStatus(@RequestParam List<Long> ids, @PathVariable int status) {
        log.info("修改商品的状态为：{}", status);
        log.info("修改商品状态的id为：{}", ids);

        List<Product> products = productService.listByIds(ids);
        if (status == 1) {
            products = products.stream().map((item) -> {
                item.setStatus(1);
                return item;
            }).collect(Collectors.toList());
        } else {
            products = products.stream().map((item) -> {
                item.setStatus(0);
                return item;
            }).collect(Collectors.toList());
        }

        log.info("商品：{}", products);
        productService.updateBatchById(products);

        return R.success("操作成功");
    }

    ;


    /**
     * 获取商品库存
     *
     * @param productId
     * @return
     */
    @GetMapping("/stock/{pid}")
    public int getStock(@PathVariable("pid") Long productId) {
        Product product = productService.getById(productId);
        return product.getStock();
    }

    /**
     * 修改商品库存
     *
     * @param
     * @return
     *//*
    @PutMapping("/stock/{id}")
    public Boolean updateStock(@PathVariable("id") Long productId) {
        Product product = productService.getById(productId);
        Integer stock = product.getStock();
        stock--;
        product.setStock(stock);
        boolean b = productService.updateById(product);
        return b ? true : false;
    }*/

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "orderPro.queue"),
            exchange = @Exchange(name = "itrui.direct", type = ExchangeTypes.DIRECT),
            key = "pro"
    ))
    public void updateStock(Long msg){
        //检查库存
        Product pro = productService.getById(msg);
        Integer stock = pro.getStock();
        if (stock <= 0){
            throw new CustomException("商品已售罄");
        } else {
            stock--;
            pro.setStock(stock);
            productService.updateById(pro);
        }

    }


    /**
     * 通过id获取商品
     *
     * @param productId
     * @return
     */
    @GetMapping("/pro/{id}")
    public Product getProductById(@PathVariable("id") Long productId) {

        Product product = productService.getById(productId);

        return product;
    }

    //TODO 普通用户接口

    /**
     * 查找用户发布商品
     *
     * @param uid
     * @return
     */
    @GetMapping("/pusher/{uid}")
    public Result selectProductByPusher(@PathVariable Long uid) {
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Product::getSeller, uid);

        List<Product> list = productService.list(queryWrapper);

        list = list.stream().map((item) -> {
            Long id = item.getId();
            List<Picture> picture = pictureClient.getPicture(id, 1);
            item.setPicture(picture);
            return item;
        }).collect(Collectors.toList());

        return new Result(Code.GET_OK, list, "查找成功");
    }

    /**
     * 获取全部商品
     *
     * @return
     */
    @GetMapping("/all")
    public Result mGetAllProduct() {

        List<Product> list = productService.list();

        list = list.stream().map((item) -> {
            Long id = item.getId();
            List<Picture> picture = pictureClient.getPicture(id, 1);
            item.setPicture(picture);
            return item;
        }).collect(Collectors.toList());

        return new Result(Code.GET_OK, list, "查找成功");
    }


    /**
     * 通过商品名查找商品
     *
     * @param _proName
     * @return
     */
    @GetMapping("/name/{_proName}")
    public Result getByName(@PathVariable String _proName) {
        System.out.println(_proName);
        String proName = "%" + _proName + "%";
        LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Product::getName, proName);
        List<Product> list = productService.list(queryWrapper);
        list = list.stream().map((item) -> {
            Long id = item.getId();
            List<Picture> picture = pictureClient.getPicture(id, 1);
            item.setPicture(picture);
            return item;
        }).collect(Collectors.toList());
        return new Result(Code.GET_OK, list, "查找成功");
    }

    /**
     * 分类查找商品
     *
     * @param _name
     * @return
     */
    @GetMapping("/type/{_name}")
    public Result getByType(@PathVariable String _name) {
        System.out.println(_name);
        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        categoryLambdaQueryWrapper.eq(Category::getName, _name);
        Category category = categoryService.getOne(categoryLambdaQueryWrapper);

        LambdaQueryWrapper<Product> productLambdaQueryWrapper = new LambdaQueryWrapper<>();
        productLambdaQueryWrapper.eq(Product::getCategoryId, category.getId());
        List<Product> list = productService.list(productLambdaQueryWrapper);

        list = list.stream().map((item) -> {
            Long id = item.getId();
            List<Picture> picture = pictureClient.getPicture(id, 1);
            item.setPicture(picture);
            return item;
        }).collect(Collectors.toList());

        return new Result(Code.GET_OK, list, "查找成功");
    }


    @PostMapping("/m")
    @Transactional
    public Result mSaveProduct(@RequestBody Product product) {
        List<String> uri = product.getPicture().stream().map((item) -> {
            return item.getUri();
        }).collect(Collectors.toList());
        boolean b = pictureClient.savePicture(uri, 1, product.getId());
        boolean save = productService.save(product);

        return new Result(save&&b ? Code.SAVE_OK : Code.SAVE_ERR, save);
    }


}
